package com.example.demo.use_demo.a_fork_join;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import com.example.demo.BusinessUtil;
import com.example.demo.person.pojo.Person;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.RecursiveTask;

/**
 * 分而治之,类似多线程那种
 * @author farben
 */
@Slf4j
public class ExcelForkTask extends RecursiveTask<List<Person>> {

    private static final long serialVersionUID = 272077780755652671L;
    private int start;

    private int end;

    private int batch;

    private Sheet sheet;

    public ExcelForkTask(int start, int end, int batch, Sheet sheet) {
        this.start = start;
        this.end = end;
        this.batch = batch;
        this.sheet = sheet;
    }

    @Override
    protected List<Person> compute() {
        if(start > end){
            return Collections.emptyList();
        }
        if(end - start < batch){
            return this.unitTask(sheet,start,end);
        } else {
            // 二分拆分
            int mid = (start + end) / 2;
            // 分别创建子任务
            ExcelForkTask leftForkTask = new ExcelForkTask(start, mid, batch, sheet);
            ExcelForkTask rightForkTask = new ExcelForkTask(mid + 1, end, batch, sheet);
            leftForkTask.fork();
            rightForkTask.fork();
            List<Person> leftResult = leftForkTask.join();
            List<Person> rightResult = rightForkTask.join();
            return new ArrayList<>(CollectionUtil.addAll(leftResult, rightResult));
        }
    }

    /**
     * 任务单元
     */
    private List<Person> unitTask(Sheet sheet, int start, int end) {
        List<Person> personList = new ArrayList<>();
        Person personTemp;
        Row rowTemp;
        for(int i = start; i <= end; i++){
            rowTemp = sheet.getRow(i);
            String jobNo = BusinessUtil.getStringCellValue(rowTemp.getCell(0));
            String name = BusinessUtil.getStringCellValue(rowTemp.getCell(1));
            personTemp = new Person();
            personTemp.setJobNo(jobNo);
            personTemp.setName(name);
            personList.add(personTemp);
        }
        log.info("Read Task (start:{} end:{} {}条)>>>......{}", start, end, personList.size(), DateUtil.format(DateUtil.date(), DatePattern.NORM_DATETIME_FORMAT));
        return personList;
    }

}
